package com.mes.schedule.manager;


import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import java.util.Map.Entry;
import java.util.jar.JarEntry;

import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import com.mes.basicdata.dao.CalendarDao;
import com.mes.basicdata.dao.CalendarDataDao;
import com.mes.basicdata.domain.Calendar;
import com.mes.basicdata.domain.CalendarData;
import com.mes.basicdata.manager.CalendarDataManager;
import com.mes.basicdata.manager.CalendarManager;
import com.mes.schedule.domain.SCalendar;
import com.mes.schedule.domain.ScheduleScheme;
import com.mes.schedule.domain.Shift;
import com.mes.schedule.domain.TimeSection;
import com.mes.schedule.manager.iface.IScheduleCalendarManager;
import com.mes.schedule.util.ScheduleUtils;


@Component("scheduleCalendarManager")
@Transactional
public class ScheduleCalendarManager implements IScheduleCalendarManager{
	private final static Log log = LogFactory
			.getLog(ScheduleCalendarManager.class);

	@javax.annotation.Resource
	private CalendarManager calendarManager;
	@javax.annotation.Resource
	private CalendarDataManager calendarDataManager;
	@javax.annotation.Resource
	private CalendarDataDao calendarDataDao;
	@javax.annotation.Resource
	private CalendarDao calendarDao;

	/**
	 * 重新初始化调度方案中所有日历
	 * 
	 * @param scheme
	 * @throws Exception
	 */
	public void reInitSchemeCalendar(ScheduleScheme scheme) throws Exception {
		for (SCalendar calendar : scheme.getCalendarMap().values()) {
			// 非系统默认日历直接更新
			if (!calendar.getCalendarUid().startsWith("SYSDC"))
				this.initCalendar(scheme, calendar.getCalendarUid());
		}
	}

	 
	/**
	 * 初始化日历
	 */
	public SCalendar initCalendar(ScheduleScheme scheme, String calendarUid)
			throws Exception {
		log.info("开始初始化日历：" + calendarUid);
		if (log.isDebugEnabled()) {
			if (calendarUid.equals("192168042071")) {
				log.debug("开始初始化日历：" + calendarUid);
			}
		}

		/*
		 * 只想刷新修改某个日历的配置怎么办 应该单独抽出一个方法 将新增和修改区分开来
		 */
		SCalendar sCalendar;
		if (scheme.getCalendarMap().containsKey(calendarUid)) {
			sCalendar = scheme.getCalendarMap().get(calendarUid);
		} else {
			sCalendar = new SCalendar();
			scheme.getCalendarMap().put(calendarUid, sCalendar);
		}
		
		Calendar calendar = (Calendar) calendarDao.getById(calendarUid);	
		if (calendar == null)
			throw new Exception("日历定义错误,找不到日历编号：" + calendarUid);

		/*try{
			BeanUtils.copyProperties(sCalendar, calendar);
			
		}catch(Exception e){
			e.printStackTrace();
		}*/
		{
			sCalendar.setCalendarUid(calendar.getCalendarUid());
			sCalendar.setCalendarName(calendar.getCalendarName());//calendarName
			sCalendar.setIsBase(calendar.getIsBase());//isBase
			sCalendar.setGroupName(calendar.getGroupName());//groupName
			sCalendar.setGroupId(calendar.getGroupId());//groupId
			sCalendar.setBaseCalendarUid(calendar.getBaseCalendarUid());//baseCalendarUid
			sCalendar.setBaseCalendar(calendar.getBaseCalendar());//baseCalendar
			sCalendar.setDeptUid(calendar.getDeptUid());//deptUid
			sCalendar.setDept(calendar.getDept());//dept
			
		}
		
		
		

		sCalendar.setStartDate(scheme.getScheduleStart());
		sCalendar.setEndDate(scheme.getScheduleFinish());

		// 一定要以前的日历信息置空
		sCalendar.setInitEndDate(null);
		sCalendar.getTimeGrid().clear();

		sCalendar.setScheme(scheme);
		
		
		try{
			List<CalendarData> selfWc = calendarDataDao
					.getWeekDayCalendarData(calendarUid);			
			sCalendar.setSelfWeekDayCalendarData(selfWc);
			List<CalendarData> selfEc = calendarDataDao.getExceptionCalendarData(
					calendarUid, sCalendar.getStartDate(), sCalendar.getEndDate());
			sCalendar.setSelfExceptionCalendarData(selfEc);
			
			CalendarData[] weekDayCalendarData = new CalendarData[7];
			List<CalendarData> exceptionCalendarData = new ArrayList<CalendarData>();
			
			// Set<CalendarData> calendarDataSet = sCalendar.getCalendarDatas();
			if (sCalendar.getBaseCalendarUid() != null
					&& !sCalendar.getBaseCalendarUid().equals("-1")) {
				SCalendar baseCalendar;
				if (scheme.getCalendarMap().containsKey(
						sCalendar.getBaseCalendarUid()))
					baseCalendar = scheme.getCalendarMap().get(
							sCalendar.getBaseCalendarUid());
				else
					baseCalendar = initCalendar(scheme, sCalendar
							.getBaseCalendarUid());
				
				// 设置日历的基准日历
				
				sCalendar.setBaseCalendar(baseCalendar);
				
				// 大部门设备都应该从此退出
				if ((selfWc == null || selfWc.isEmpty())
						&& (selfEc == null || selfEc.isEmpty())) {
					// 存在基准且不存在任何例外
					if (sCalendar.getBaseCalendarUid() != null)
						sCalendar.setSameWithBase(true);
					// sCalendar.setNoCapacity(baseCalendar.getNoCapacity());
					
					// 叠加之后的日历数据
					// sCalendar.setWeekDayCalendarData(baseCalendar
					// .getWeekDayCalendarData());
					// sCalendar.setExceptionCalendarData(baseCalendar
					// .getExceptionCalendarData());
					// sCalendar.setTimeGrid(baseCalendar.getTimeGrid());
					// scheme.getCalendarMap().put(calendarUid, sCalendar);
					return sCalendar;
					
				}
				
				sCalendar.setSameWithBase(false);
				CalendarData[] baseWeekDayCalendarData = baseCalendar
						.getWeekDayCalendarData();
				for (int i = 0; i < 7; i++) {
					// //每天的日历可能会改，所以需要新建
					// CalendarData calendarData=new CalendarData();
					// BeanUtils.copyProperties(calendarData,);
					weekDayCalendarData[i] = baseWeekDayCalendarData[i];
				}
				for (CalendarData calendarData : baseCalendar
						.getExceptionCalendarData()) {
					exceptionCalendarData.add(calendarData);
				}
				// for(CalendarData calendarData:calendarDataSet)
				// {
				// //calendarData.getDayOrException()-1一定要减一
				// if(calendarData.getDayOrException()>0&&calendarData.getDayOrException()<8)
				// weekDayCalendarData[calendarData.getDayOrException()-1]=calendarData;
				// else
				// exceptionCalendarData.add(calendarData);
				// }
			}
			
			if (selfWc != null && selfWc.size() > 0) {
				for (CalendarData calendarData : selfWc) {
					if (calendarData.getDayOrException() > 0
							&& calendarData.getDayOrException() < 8)
						weekDayCalendarData[(int) (calendarData.getDayOrException() - 1)] = calendarData;
				}
			}
			if (selfEc != null && selfEc.size() > 0) {
				for (CalendarData calendarData : selfEc)
					exceptionCalendarData.add(calendarData);
			}
			// 叠加之后的日历数据
			sCalendar.setWeekDayCalendarData(weekDayCalendarData);
			sCalendar.setExceptionCalendarData(exceptionCalendarData);
			
			IdentityNoCapacityCalendar(sCalendar);
		}catch(Exception e){
			e.printStackTrace();
		}


		// 以下这两个函数应该考虑合并，去掉timesection类变量
		// lqm todo
		// initTimeSection(sCalendar);
		// createTimeGrid(sCalendar);
		// sCalendar.setIdleSections(idleSections);

		log.debug("结束初始化日历：" + calendarUid);
		return sCalendar;
	}

	private void IdentityNoCapacityCalendar(SCalendar sCalendar) {
		sCalendar.setNoCapacity(false);
		// 将无能力设备标示出
		// lqm todo
		// 暂时比较简单粗暴
		boolean isWorking = false;
		CalendarData[] weekDayCalendarData = sCalendar.getWeekDayCalendarData();
		for (int i = 0; i < 7; i++) {
			CalendarData cd = weekDayCalendarData[i];
			if (cd != null && cd.getIsWorking() != null && cd.getIsWorking()) {
				isWorking = true;
				break;
			}
		}

		if (!isWorking) {
			for (CalendarData cd : sCalendar.getExceptionCalendarData()) {
				if (cd != null && cd.getIsWorking() != null
						&& cd.getIsWorking()) {
					isWorking = true;
					break;
				}
			}

			if (!isWorking)
				sCalendar.setNoCapacity(true);

		}
	}

	private void initTimeSection(SCalendar sCalendar, Date endDate) {
		synchronized (sCalendar) {
			Date startDate = (sCalendar.getInitEndDate() == null) ? sCalendar
					.getStartDate() : sCalendar.getInitEndDate();
			// 下面暂时不支持
			java.util.Calendar calendar = java.util.Calendar.getInstance();
			calendar.setTime(endDate);
			ScheduleScheme scheduleScheme = sCalendar.getScheme();
			// 将小时与分钟减去
			calendar.set(java.util.Calendar.HOUR_OF_DAY, 0);
			calendar.set(java.util.Calendar.MINUTE, 0);
			calendar.set(java.util.Calendar.SECOND, 0);
			calendar.set(java.util.Calendar.MILLISECOND, 0);
			endDate = calendar.getTime();

			if (endDate.getTime() <= startDate.getTime())
				return;

			log.info("初始化日历区间 " + sCalendar.getCalendarName() + "开始时间"
					+ startDate + " ,截至时间为：" + endDate);

			CalendarData[] weekDayCalendarData = sCalendar
					.getWeekDayCalendarData();
			List<CalendarData> exceptionCalendarData = sCalendar
					.getExceptionCalendarData();

			Map<Integer, Date[][]> shiftOfWeek = new TreeMap<Integer, Date[][]>();
			Map<Integer, Integer[]> shiftIndexWeek = new TreeMap<Integer, Integer[]>();
			for (int i = 1; i < 8; i++) {
				CalendarData data = weekDayCalendarData[i - 1];

				if (data != null && data.getIsWorking()) {
					Date[][] shift = new Date[8][2];
					Integer[] shiftIndex = new Integer[8];
					shift[0][0] = data.getFirstShiftFromTime();
					shift[0][1] = data.getFirstShiftToTime();
					shift[1][0] = data.getSecondShiftFromTime();
					shift[1][1] = data.getSecondShiftToTime();
					shift[2][0] = data.getThirdShiftFromTime();
					shift[2][1] = data.getThirdShiftToTime();
					shift[3][0] = data.getFourthShiftFromTime();
					shift[3][1] = data.getFourthShiftToTime();
					shift[4][0] = data.getFifthShiftFromTime();
					shift[4][1] = data.getFifthShiftToTime();
					shift[5][0] = data.getSixthShiftFromTime();
					shift[5][1] = data.getSixthShiftToTime();
					shift[6][0] = data.getSeventhShiftFromTime();
					shift[6][1] = data.getSeventhShiftToTime();
					shift[7][0] = data.getEighthShiftFromTime();
					shift[7][1] = data.getEighthShiftToTime();

					shiftIndex[0] = data.getShift1().intValue();
					shiftIndex[1] = data.getShift2().intValue();
					shiftIndex[2] = data.getShift3().intValue();
					shiftIndex[3] = data.getShift4().intValue();
					shiftIndex[4] = data.getShift5().intValue();
					shiftIndex[5] = data.getShift6().intValue();
					shiftIndex[6] = data.getShift7().intValue();
					shiftIndex[7] = data.getShift8().intValue();

					shiftOfWeek.put(i, shift);
					shiftIndexWeek.put(i, shiftIndex);
				} else {
					shiftOfWeek.put(i, null);
					shiftIndexWeek.put(i, null);
				}

			}
			// TreeMap<Long, Long> idleSections = new TreeMap<Long, Long>();
			TreeMap<TimeSection, Integer> timeSectionMap = new TreeMap<TimeSection, Integer>();
			TreeMap<TimeSection, Integer> shiftSectionMap = new TreeMap<TimeSection, Integer>();
			TreeMap<TimeSection, Shift> shiftProductionSectionMap = new TreeMap<TimeSection, Shift>();
			java.util.Calendar temp = java.util.Calendar.getInstance();
			temp.setTime(startDate);
			temp.set(java.util.Calendar.HOUR_OF_DAY, 0);
			temp.set(java.util.Calendar.MINUTE, 0);
			temp.set(java.util.Calendar.SECOND, 0);
			temp.set(java.util.Calendar.MILLISECOND, 0);
			int day = 0;
			// todo 每周如此重复，
			// 效率有提高空间
			Date fromTime, toTime;
			int realShift = 0;
			int shiftMemory = realShift;
			Shift shiftProduction = new Shift();
			while (temp.getTime().before(endDate)) {
				// SUNDAY：1
				int dayOfweek = temp.get(java.util.Calendar.DAY_OF_WEEK);
				Date[][] shift = shiftOfWeek.get(dayOfweek);
				Integer[] shiftIndex = shiftIndexWeek.get(dayOfweek);
				java.util.Calendar temp1 = java.util.Calendar.getInstance();
				java.util.Calendar temp2 = java.util.Calendar.getInstance();
				if (shift != null) {
					for (int i = 0; i < 4; i++) {
						fromTime = shift[i][0];
						toTime = shift[i][1];
						if (shiftIndex[i] != null)
							realShift = shiftIndex[i];
						if (fromTime != null && toTime != null) {
							temp1.setTime(fromTime);
							int hourOfDay = temp1
									.get(java.util.Calendar.HOUR_OF_DAY);
							int min = temp1.get(java.util.Calendar.MINUTE);
							long start = hourOfDay * 60 + min;

							temp2.setTime(toTime);
							int hourOfDayTo = temp2
									.get(java.util.Calendar.HOUR_OF_DAY);
							int minTo = temp2.get(java.util.Calendar.MINUTE);
							long end = hourOfDayTo * 60 + minTo;
							// idleSections.put(start + 1440 * day, end + 1440 *
							// day);
							// lqm todo
							// 只允许在第一个班次上定义全日工作
							if (end < start || (end == start && i == 0)) {
								end = (hourOfDayTo + 24) * 60 + minTo;
							}
							timeSectionMap.put(new TimeSection(start + 1440
									* day, end + 1440 * day), 1);
							// 新建班次
							if (shiftMemory != realShift) {
								// 班次发生变化则需要新建
								shiftProduction = new Shift();
								shiftProduction.setCalendarUid(sCalendar
										.getCalendarUid());
								shiftProduction.setSCalendar(sCalendar);
								shiftProduction.setShiftId(realShift);
								shiftProduction.setShiftStartTime(fromTime);
								shiftProduction.setShiftEndTime(toTime);
								shiftProduction
										.setShiftStartSegment((int) (start / scheduleScheme
												.getScheduleInterval()));
								shiftProduction
										.setShiftEndSegment((int) (end / scheduleScheme
												.getScheduleInterval()));
								shiftProduction.setAvailableShiftTime(end
										- start);
								shiftMemory = realShift;
							} else {
								shiftProduction.setShiftEndTime(toTime);
								shiftProduction
										.setShiftEndSegment((int) (end / scheduleScheme
												.getScheduleInterval()));
								shiftProduction
										.setAvailableShiftTime(shiftProduction
												.getAvailableShiftTime()
												+ (end - start));
							}
							shiftProductionSectionMap.put(new TimeSection(start
									+ 1440 * day, end + 1440 * day),
									shiftProduction);
							// 为了区分相同名称的班次，对realShift进行处理,十位数为一周的第几天，个位数为当前天的班次号
							shiftSectionMap.put(new TimeSection(start + 1440
									* day, end + 1440 * day), (dayOfweek + 1)
									* 10 + realShift);
						}
					}
					shiftMemory = 0;
					for (int i = 4; i < 8; i++) {
						fromTime = shift[i][0];
						toTime = shift[i][1];
						if (shiftIndex[i] != null)
							realShift = shiftIndex[i];
						if (fromTime != null && toTime != null) {
							temp1.setTime(fromTime);
							int hourOfDay = temp1
									.get(java.util.Calendar.HOUR_OF_DAY);
							int min = temp1.get(java.util.Calendar.MINUTE);
							long start = hourOfDay * 60 + min;
							temp2.setTime(toTime);
							int hourOfDayTo = temp2
									.get(java.util.Calendar.HOUR_OF_DAY);
							int minTo = temp2.get(java.util.Calendar.MINUTE);
							long end = hourOfDayTo * 60 + minTo;
							// idleSections.put(start + 1440 * day, end + 1440 *
							// day);
							if (end < start) {
								end = (hourOfDayTo + 24) * 60 + minTo;
							}
							timeSectionMap.put(new TimeSection(start + 1440
									* day, end + 1440 * day), 2);
							// 新建班次
							if (shiftMemory != realShift) {
								// 班次发生变化则需要新建
								shiftProduction = new Shift();
								shiftProduction.setCalendarUid(sCalendar
										.getCalendarUid());
								shiftProduction.setSCalendar(sCalendar);
								shiftProduction.setShiftId(realShift);
								shiftProduction.setShiftStartTime(fromTime);
								shiftProduction.setShiftEndTime(toTime);
								shiftProduction
										.setShiftStartSegment((int) (start / scheduleScheme
												.getScheduleInterval()));
								shiftProduction
										.setShiftEndSegment((int) (end / scheduleScheme
												.getScheduleInterval()));
								shiftProduction.setAvailableShiftTime(end
										- start);
								shiftMemory = realShift;
							} else {
								shiftProduction.setShiftEndTime(toTime);
								shiftProduction
										.setShiftEndSegment((int) (end / scheduleScheme
												.getScheduleInterval()));
								shiftProduction
										.setAvailableShiftTime(shiftProduction
												.getAvailableShiftTime()
												+ (end - start));
							}
							shiftProductionSectionMap.put(new TimeSection(start
									+ 1440 * day, end + 1440 * day),
									shiftProduction);
							shiftSectionMap.put(new TimeSection(start + 1440
									* day, end + 1440 * day), (dayOfweek + 1)
									* 10 + realShift);
						}
					}
				}
				temp.add(java.util.Calendar.DAY_OF_YEAR, 1);
				day++;
			}

			temp.setTime(startDate);
			temp.set(java.util.Calendar.HOUR_OF_DAY, 0);
			temp.set(java.util.Calendar.MINUTE, 0);
			temp.set(java.util.Calendar.SECOND, 0);
			temp.set(java.util.Calendar.MILLISECOND, 0);

			java.util.Calendar temp1 = java.util.Calendar.getInstance();
			java.util.Calendar temp2 = java.util.Calendar.getInstance();
			shiftMemory = 0;
			for (CalendarData data : exceptionCalendarData) {

				Date fromDate = data.getFromDate();
				Date toDate = data.getToDate();

				if (fromDate == null || toDate == null) {
					log.warn("例外日历定义不完整！日历编号为：" + data.getCalendarUid());
					continue;
				}
				if (fromDate.compareTo(endDate) >= 0
						|| toDate.compareTo(startDate) <= 0) {

				} else {

					temp1.setTime(fromDate);
					temp1.set(java.util.Calendar.HOUR_OF_DAY, 0);
					temp1.set(java.util.Calendar.MINUTE, 0);
					temp1.set(java.util.Calendar.SECOND, 0);
					temp1.set(java.util.Calendar.MILLISECOND, 0);

					temp2.setTime(toDate);
					/*
					 * by lqm ，例外日历计算时自动向后延一天 主要是考虑人的操作习惯
					 */
					temp2.add(java.util.Calendar.DATE, 1);
					toDate = temp2.getTime();

					temp2.set(java.util.Calendar.HOUR_OF_DAY, 0);
					temp2.set(java.util.Calendar.MINUTE, 0);
					temp2.set(java.util.Calendar.SECOND, 0);
					temp2.set(java.util.Calendar.MILLISECOND, 0);

					// temp2.add(java.util.Calendar.DATE, 1);
					int fromDay = 0;
					int toDay = 0;
					long from = 0l;
					long to = 1l;

					if (fromDate.compareTo(startDate) >= 0
							&& toDate.compareTo(endDate) <= 0) {
						from = (temp1.getTime().getTime() - temp.getTime()
								.getTime()) / 60000;
						to = (temp2.getTime().getTime() - temp.getTime()
								.getTime()) / 60000;
						fromDay = (int) ((temp1.getTime().getTime() - temp
								.getTime().getTime()) / 60000 / 60 / 24);
						toDay = (int) ((temp2.getTime().getTime() - temp
								.getTime().getTime()) / 60000 / 60 / 24);
					} else {
						if (fromDate.compareTo(startDate) <= 0
								&& toDate.compareTo(endDate) >= 0) {
							from = 0;
							to = (endDate.getTime() - temp.getTime().getTime()) / 60000;
							fromDay = 0;
							toDay = (int) ((endDate.getTime() - temp.getTime()
									.getTime()) / 60000 / 60 / 24);
						}
						if (fromDate.compareTo(startDate) <= 0
								&& toDate.compareTo(endDate) <= 0) {
							from = 0;
							to = (temp2.getTime().getTime() - temp.getTime()
									.getTime()) / 60000;
							fromDay = 0;
							toDay = (int) ((temp2.getTime().getTime() - temp
									.getTime().getTime()) / 60000 / 60 / 24);
						}
						if (fromDate.compareTo(startDate) >= 0
								&& toDate.compareTo(endDate) >= 0) {
							from = (temp1.getTime().getTime() - temp.getTime()
									.getTime()) / 60000;
							to = (endDate.getTime() - temp.getTime().getTime()) / 60000;
							fromDay = (int) ((temp1.getTime().getTime() - temp
									.getTime().getTime()) / 60000 / 60 / 24);
							toDay = (int) ((endDate.getTime() - temp.getTime()
									.getTime()) / 60000 / 60 / 24);
						}
					}

					Set<Entry<TimeSection, Integer>> entries = timeSectionMap
							.entrySet();
					Iterator<Entry<TimeSection, Integer>> itor = entries
							.iterator();

					Set<Entry<TimeSection, Integer>> entriesShift = shiftSectionMap
							.entrySet();
					Set<TimeSection> keySet = new HashSet<TimeSection>();
					while (itor.hasNext()) {
						Entry<TimeSection, Integer> k = itor.next();
						// 这个条件太严格
						// if (k.getKey().getStart() >= from &&
						// k.getKey().getEnd() <= to) {
						// keySet.add(k.getKey());
						// }

						// 只要时间片在例外区，均移除，而不管是否是工作日，如果是工作日则会在后面将工作时间片段加进来
						if (k.getKey().getStart() >= from
								&& k.getKey().getStart() <= to) {
							keySet.add(k.getKey());
						}

					}
					for (TimeSection key : keySet) {
						timeSectionMap.remove(key);
						shiftSectionMap.remove(key);
						// 设置例外日历时要更新班次的可用时间
						Shift shiftPro = shiftProductionSectionMap.get(key);
						long startMinute = key.getStart();
						long endMinute = key.getEnd();
						shiftPro.setAvailableShiftTime(shiftPro
								.getAvailableShiftTime()
								- (endMinute - startMinute));
						shiftProductionSectionMap.remove(key);

					}
					if (!data.getIsWorking()) {

					} else {
						Date[][] shift = new Date[8][2];
						Integer[] shiftIndex = new Integer[8];
						shift[0][0] = data.getFirstShiftFromTime();
						shift[0][1] = data.getFirstShiftToTime();
						shift[1][0] = data.getSecondShiftFromTime();
						shift[1][1] = data.getSecondShiftToTime();
						shift[2][0] = data.getThirdShiftFromTime();
						shift[2][1] = data.getThirdShiftToTime();
						shift[3][0] = data.getFourthShiftFromTime();
						shift[3][1] = data.getFourthShiftToTime();
						shift[4][0] = data.getFifthShiftFromTime();
						shift[4][1] = data.getFifthShiftToTime();
						shift[5][0] = data.getSixthShiftFromTime();
						shift[5][1] = data.getSixthShiftToTime();
						shift[6][0] = data.getSeventhShiftFromTime();
						shift[6][1] = data.getSeventhShiftToTime();

						shiftIndex[0] = data.getShift1().intValue();
						shiftIndex[1] = data.getShift2().intValue();
						shiftIndex[2] = data.getShift3().intValue();
						shiftIndex[3] = data.getShift4().intValue();
						shiftIndex[4] = data.getShift5().intValue();
						shiftIndex[5] = data.getShift6().intValue();
						shiftIndex[6] = data.getShift7().intValue();
						shiftIndex[7] = data.getShift8().intValue();

						// todo 每天如此重复，
						// 效率有提高空间
						for (int exceptionDay = fromDay; exceptionDay < toDay; exceptionDay++) {
							for (int i = 0; i < 8; i++) {
								fromTime = shift[i][0];
								toTime = shift[i][1];
								if (shiftIndex[i] != null)
									realShift = shiftIndex[i];
								temp1 = java.util.Calendar.getInstance();
								temp2 = java.util.Calendar.getInstance();
								if (fromTime != null && toTime != null) {
									temp1.setTime(fromTime);
									int hourOfDay = temp1
											.get(java.util.Calendar.HOUR_OF_DAY);
									int min = temp1
											.get(java.util.Calendar.MINUTE);
									long start = hourOfDay * 60 + min;

									temp2.setTime(toTime);
									int hourOfDayTo = temp2
											.get(java.util.Calendar.HOUR_OF_DAY);
									int minTo = temp2
											.get(java.util.Calendar.MINUTE);
									long end = hourOfDayTo * 60 + minTo;
									if (end <= start) {
										end = (hourOfDayTo + 24) * 60 + minTo;
									}
									/*
									 * timeSection.put(start + 1440
									 * exceptionDay, end + 1440 exceptionDay);
									 */
									timeSectionMap.put(new TimeSection(start
											+ 1440 * exceptionDay, end + 1440
											* exceptionDay), 3);
									// 新建班次
									if (shiftMemory != realShift) {
										// 班次发生变化则需要新建
										shiftProduction = new Shift();
										shiftProduction
												.setCalendarUid(sCalendar
														.getCalendarUid());
										shiftProduction.setSCalendar(sCalendar);
										shiftProduction.setShiftId(realShift);
										shiftProduction
												.setShiftStartTime(fromTime);
										shiftProduction.setShiftEndTime(toTime);
										shiftProduction
												.setShiftStartSegment((int) (start / scheduleScheme
														.getScheduleInterval()));
										shiftProduction
												.setShiftEndSegment((int) (end / scheduleScheme
														.getScheduleInterval()));
										shiftProduction
												.setAvailableShiftTime(end
														- start);
										shiftMemory = realShift;
									} else {
										shiftProduction.setShiftEndTime(toTime);
										shiftProduction
												.setShiftEndSegment((int) (end / scheduleScheme
														.getScheduleInterval()));
										shiftProduction
												.setAvailableShiftTime(shiftProduction
														.getAvailableShiftTime()
														+ (end - start));
									}
									shiftProductionSectionMap.put(
											new TimeSection(start + 1440 * day,
													end + 1440 * day),
											shiftProduction);
									shiftSectionMap.put(new TimeSection(start
											+ 1440 * exceptionDay, end + 1440
											* exceptionDay), (exceptionDay + 1)
											* 10 + realShift);
								}
							}
						}

					}
				}

			}
			if (timeSectionMap.size() == 0)
				log.error("严重错误，日历:" + sCalendar + " 可用工作区间数为0，可能会导致调度结果出现异常！");

			Map<Integer, Integer> capacity = sCalendar.getTimeGrid();
			Map<Integer, Integer> shiftMap = sCalendar.getShiftGrid();
			Map<Integer, Shift> shiftProdcutionGrid = sCalendar
					.getShiftProductionGrid();

			int thisStartSegment = scheduleScheme
					.calSegementFromDate(startDate);

			for (Entry<TimeSection, Integer> entry : timeSectionMap.entrySet()) {
				TimeSection timeSection = entry.getKey();

				int start = (int) (timeSection.getStart() / scheduleScheme
						.getScheduleInterval());
				int end = (int) (timeSection.getEnd() / scheduleScheme
						.getScheduleInterval());
				for (int i = start; i < end; i++) {
					capacity
							.put(thisStartSegment + i, SCalendar.CALENDAR_NOMAL);
					// capacity.set(i, SCalendar.CALENDAR_NOMAL);
				}
			}
			// 建立时间片段和shift的关系
			for (Entry<TimeSection, Shift> entry : shiftProductionSectionMap
					.entrySet()) {
				TimeSection timeSection = entry.getKey();
				Shift shiftPro = entry.getValue();
				int start = (int) (timeSection.getStart() / scheduleScheme
						.getScheduleInterval());
				int end = (int) (timeSection.getEnd() / scheduleScheme
						.getScheduleInterval());
				for (int i = start; i < end; i++) {
					shiftProdcutionGrid.put(thisStartSegment + i, shiftPro);
					// capacity.set(i, SCalendar.CALENDAR_NOMAL);
				}
			}
			for (Entry<TimeSection, Integer> entry : shiftSectionMap.entrySet()) {
				TimeSection shiftSection = entry.getKey();
				int shift = entry.getValue();
				int start = (int) (shiftSection.getStart() / scheduleScheme
						.getScheduleInterval());
				int end = (int) (shiftSection.getEnd() / scheduleScheme
						.getScheduleInterval());
				for (int i = start; i < end; i++) {
					shiftMap.put(thisStartSegment + i, shift);
				}
			}
			// createTimeGrid(sCalendar,timeSectionMap);
			// 设置结束日期
			sCalendar.setInitEndDate(endDate);

			log.debug("结束初始化日历工作区间initTimeSection，总可用工作区间数为："
					+ timeSectionMap.size());
		}
	}

	 
	public SCalendar saveException(ScheduleScheme scheme,
			List<CalendarData> exceptionCalendarDataList) throws Exception {
//		this.calendarDataManager.save(exceptionCalendarDataList);
		return null;
	}

	 
	public List<SCalendar> getBaseCalendarList(String scheduleUid)
			throws Exception {
		// TODO Auto-generated method stub
		ScheduleScheme scheme = ScheduleUtils.getScheduleScheme(scheduleUid);
		List<SCalendar> calendarList = new ArrayList<SCalendar>();
		for (SCalendar sc : scheme.getCalendarMap().values()) {
			if (sc.getIsBase()) {
				calendarList.add(sc);
			}
		}

		return calendarList;
	}

	 
	public SCalendar getCalendar(ScheduleScheme scheme, String calendarUid)
			throws Exception {
		// ScheduleScheme scheme = ScheduleUtils.getScheduleScheme(scheduleUid);
		if (scheme.getCalendarMap().containsKey(calendarUid))
			return scheme.getCalendarMap().get(calendarUid);
		else {
			return this.initCalendar(scheme, calendarUid);
		}

	}

	 
	public void updateCalendar(SCalendar scheduleCalendar) throws Exception {

		// 更新到数据库
		Calendar calendar = (Calendar) calendarDao.getById(scheduleCalendar
				.getCalendarUid());
		if (calendar != null) {
			calendar.setBaseCalendarUid(scheduleCalendar.getBaseCalendarUid());
			// calendar.setCalendarName(scheduleCalendar.getCalendarName());

			calendarManager.update(calendar);

			// List<CalendarData>
			// exceptionCalendarDataList=scheduleCalendar.getExceptionCalendarData();
//			calendarDataManager.save(scheduleCalendar
//					.getExceptionCalendarData());
		}
		// ScheduleScheme scheme=scheduleCalendar.getScheme();
		// //如果基准日历没有初始化，则进行基准日历初始化
		// 初始化中本来就有这一段逻辑
		// if(!(scheme.getCalendarMap().containsKey(scheduleCalendar.getBaseCalendarUid())))
		// {
		// this.initCalendar(scheme, scheduleCalendar.getBaseCalendarUid());
		// }

		// 重新初始化该日历的工作时间

		this.initCalendar(scheduleCalendar.getScheme(), scheduleCalendar
				.getCalendarUid());

	}

	public CalendarManager getCalendarManager() {
		return calendarManager;
	}

	public void setCalendarManager(CalendarManager calendarManager) {
		this.calendarManager = calendarManager;
	}

	public CalendarDataManager getCalendarDataManager() {
		return calendarDataManager;
	}

	public void setCalendarDataManager(CalendarDataManager calendarDataManager) {
		this.calendarDataManager = calendarDataManager;
	}

	private void createTimeGrid(SCalendar calendar,
			TreeMap<TimeSection, Integer> timeSection) {
		ScheduleScheme scheme = calendar.getScheme();
		int interval = scheme.getScheduleInterval();

		if (calendar == null)
			return;
		int totalSegment = scheme.getTotalSegement();

		Map<Integer, Integer> capacity = calendar.getTimeGrid();

		// if (calendar.getTimeSection() == null)
		// throw new Exception(calendar + " 对应的日历尚未初始化,日历编号为:" +
		// calendar.getCalendarUid());
		// TreeMap<TimeSection, Integer> timeSection =
		// calendar.getTimeSection();
		Set<Entry<TimeSection, Integer>> entries = timeSection.entrySet();
		Iterator<Entry<TimeSection, Integer>> itor = entries.iterator();
		long lastEnd = 0;
		int count = 0;
		while (itor.hasNext()) {
			Entry<TimeSection, Integer> k = itor.next();
			int unavalibleCount = Math.round((k.getKey().getStart() - lastEnd)
					/ (float) interval);

			// throw java.lang.ArrayIndexOutOfBoundsException :35168
			// for (int i = count; i < totalSegment && i < count +
			// unavalibleCount; i++) {
			// capacity[i] = SCalendar.CALENDAR_CLOSINGTIME;
			// }

			count += unavalibleCount;
			int avalibleCount = Math.round((k.getKey().getEnd() - k.getKey()
					.getStart())
					/ (float) interval);
			// 暂时加班,例外，正常加班没有区别
			// todo,以后要考虑
			// if (k.getValue() >= 1) {
			for (int i = count; i < totalSegment && i < count + avalibleCount; i++) {
				capacity.put(i, SCalendar.CALENDAR_NOMAL);
				// capacity.set(i, SCalendar.CALENDAR_NOMAL);

			}
			// }
			// 暂时加班,例外，正常加班没有区别

			// if (k.getValue() == 2) {
			// for (int i = count; i < totalSegment
			// && i < count + avalibleCount; i++) {
			// capacity[i][0] = Device.DEVICE_OVERTIME;
			// capacity[i][1] = Device.DEVICE_IDLE;
			//
			// }
			// }
			count += avalibleCount;
			lastEnd = k.getKey().getEnd();
		}

		if (lastEnd / interval != totalSegment) {
			int unavalibleCount = (int) (totalSegment - lastEnd / interval);
			for (int i = (int) lastEnd / interval; i < unavalibleCount; i++) {
				capacity.remove(i);
			}
		}
		// calendar.setTimeGrid(capacity);

	}

	public CalendarDataDao getCalendarDataDao() {
		return calendarDataDao;
	}

	public void setCalendarDataDao(CalendarDataDao calendarDataDao) {
		this.calendarDataDao = calendarDataDao;
	}

	public CalendarDao getCalendarDao() {
		return calendarDao;
	}

	public void setCalendarDao(CalendarDao calendarDao) {
		this.calendarDao = calendarDao;
	}

	@Transactional
	 
	public SCalendar saveCalendarData(ScheduleScheme scheme,
			List<CalendarData> CalendarDataList) throws Exception {
//		this.calendarDataManager.save(CalendarDataList);
		return null;
	}

	@Transactional
	 
	public SCalendar saveCalendarWeekDay(ScheduleScheme scheme,
			List<CalendarData> weekDayCalendarDataList) throws Exception {
//		this.calendarDataManager.save(weekDayCalendarDataList);
		return null;
	}

	@Transactional
	 
	public SCalendar saveCalendarData(ScheduleScheme scheme,
			String calendarUid, List<CalendarData> CalendarDataList)
			throws Exception {
		// 更新到数据库
		// Calendar calendar = (Calendar) calendarManager.getById(calendarUid);
		// if (calendar != null) {

		// List<CalendarData>
		// exceptionCalendarDataList=scheduleCalendar.getExceptionCalendarData();
//		calendarDataManager.save(CalendarDataList);
		// }
		// ScheduleScheme scheme=scheduleCalendar.getScheme();
		// //如果基准日历没有初始化，则进行基准日历初始化
		// 初始化中本来就有这一段逻辑
		// if(!(scheme.getCalendarMap().containsKey(scheduleCalendar.getBaseCalendarUid())))
		// {
		// this.initCalendar(scheme, scheduleCalendar.getBaseCalendarUid());
		// }

		// 重新初始化该日历的工作时间

		SCalendar sCalendar = this.initCalendar(scheme, calendarUid);

		// 如果修改的是基准日历，所有相关日历都要发生变化
		// 这里应该用递归
		// todo lqm

		for (SCalendar cc : scheme.getCalendarMap().values()) {
			if (calendarUid.equals(cc.getBaseCalendarUid())) {
				this.initCalendar(scheme, cc.getCalendarUid());
			}
		}

		return sCalendar;

	}

	 
	public int getSegementCalendar(SCalendar calendar, int segement) {

		SCalendar cal = calendar.getSameWithBase() ? (SCalendar) calendar
				.getBaseCalendar() : calendar;

		if (cal.getCalendarUid().equals("656")) {
			log.debug("aaaaaaaaaaa");
		}

		ScheduleScheme scheme = cal.getScheme();
		if (scheme == null) {
			log.error("日历调度方案为空" + calendar);
		}
		Date requestDate = scheme.calDateFromSegement(segement);
		// initEndDate上次初始化截止日期
		if (cal.getInitEndDate() == null
				|| requestDate.after(cal.getInitEndDate())) {

			// 自动扩展30天
			// 这下面的类型范围还没有弄清楚，86400000*30为一负值，必须加上d
			// 用双精度计算
			long ltime = requestDate.getTime() + (long) (86400000 * 30d);
			Date initEndDate = new Date(ltime);
			this.initTimeSection(cal, initEndDate);
		}

		Integer segementCalendar = cal.getTimeGrid().get(segement);
		if (segementCalendar == null)
			segementCalendar = SCalendar.CALENDAR_CLOSINGTIME;

		return segementCalendar;

	}

	/**
	 * 初始化系统内置日历 hba 系统默认日历中添加了
	 * 
	 * @param scheme
	 */
	 
	public void initSystemDefaultCalendar(ScheduleScheme scheme) {
		log.debug("开始初始化系统日历");
		SCalendar sCalendar = new SCalendar();
		sCalendar.setCalendarUid(SCalendar.DEFAULT_CALENDAR_STANDARD_24H);
		sCalendar.setCalendarName("系统标准24小时日历");
		sCalendar.setInitEndDate(null);
		sCalendar.getTimeGrid().clear();
		sCalendar.setScheme(scheme);
		sCalendar.setStartDate(scheme.getScheduleStart());
		sCalendar.setEndDate(scheme.getScheduleFinish());
		CalendarData[] weekDayCalendarData = new CalendarData[7];
		java.util.Calendar calendar = java.util.Calendar.getInstance();
		calendar.set(java.util.Calendar.HOUR_OF_DAY, 0);
		calendar.set(java.util.Calendar.MINUTE, 0);
		calendar.set(java.util.Calendar.SECOND, 0);
		calendar.set(java.util.Calendar.MILLISECOND, 0);
		for (int i = 0; i < 7; i++) {
			CalendarData cd = new CalendarData();
			cd.setDayOrException(i);
			cd.setIsWorking(true);
			cd.setFirstShiftFromTime(calendar.getTime());
			cd.setFirstShiftToTime(calendar.getTime());
			// 设置第一个班次为白班
			cd.setShift1(1);
			weekDayCalendarData[i] = cd;
		}

		sCalendar.setWeekDayCalendarData(weekDayCalendarData);

		scheme.getCalendarMap().put(sCalendar.getCalendarUid(), sCalendar);

		sCalendar = new SCalendar();
		sCalendar.setCalendarUid(SCalendar.DEFAULT_CALENDAR_STANDARD_ONESHIFT);
		sCalendar.setCalendarName("系统标准单班日历");
		sCalendar.setInitEndDate(null);
		sCalendar.getTimeGrid().clear();
		sCalendar.setScheme(scheme);
		sCalendar.setStartDate(scheme.getScheduleStart());
		sCalendar.setEndDate(scheme.getScheduleFinish());
		weekDayCalendarData = new CalendarData[7];
		calendar.set(java.util.Calendar.MINUTE, 0);
		calendar.set(java.util.Calendar.SECOND, 0);
		calendar.set(java.util.Calendar.MILLISECOND, 0);
		for (int i = 1; i < 6; i++) {
			CalendarData cd = new CalendarData();
			cd.setDayOrException(i);
			cd.setIsWorking(true);
			calendar.set(java.util.Calendar.HOUR_OF_DAY, 8);
			cd.setFirstShiftFromTime(calendar.getTime());
			calendar.set(java.util.Calendar.HOUR_OF_DAY, 12);
			cd.setFirstShiftToTime(calendar.getTime());
			calendar.set(java.util.Calendar.HOUR_OF_DAY, 14);
			cd.setSecondShiftFromTime(calendar.getTime());
			calendar.set(java.util.Calendar.HOUR_OF_DAY, 18);
			cd.setSecondShiftToTime(calendar.getTime());
			// 白班由两个时间段组成
			cd.setShift1(1);
			cd.setShift2(1);
			weekDayCalendarData[i] = cd;
		}
		sCalendar.setWeekDayCalendarData(weekDayCalendarData);
		scheme.getCalendarMap().put(sCalendar.getCalendarUid(), sCalendar);

		sCalendar = new SCalendar();
		sCalendar.setCalendarUid(SCalendar.DEFAULT_CALENDAR_STANDARD_TWOSHIFT);
		sCalendar.setCalendarName("系统标准两班日历");
		sCalendar.setInitEndDate(null);
		sCalendar.getTimeGrid().clear();
		sCalendar.setScheme(scheme);
		sCalendar.setStartDate(scheme.getScheduleStart());
		sCalendar.setEndDate(scheme.getScheduleFinish());
		weekDayCalendarData = new CalendarData[7];
		calendar.set(java.util.Calendar.MINUTE, 0);
		calendar.set(java.util.Calendar.SECOND, 0);
		calendar.set(java.util.Calendar.MILLISECOND, 0);
		for (int i = 0; i < 7; i++) {
			CalendarData cd = new CalendarData();
			cd.setDayOrException(i);
			cd.setIsWorking(true);
			calendar.set(java.util.Calendar.HOUR_OF_DAY, 8);
			cd.setFirstShiftFromTime(calendar.getTime());
			calendar.set(java.util.Calendar.HOUR_OF_DAY, 12);
			cd.setFirstShiftToTime(calendar.getTime());
			calendar.set(java.util.Calendar.HOUR_OF_DAY, 14);
			cd.setSecondShiftFromTime(calendar.getTime());
			calendar.set(java.util.Calendar.HOUR_OF_DAY, 18);
			cd.setSecondShiftToTime(calendar.getTime());
			calendar.set(java.util.Calendar.HOUR_OF_DAY, 18);
			cd.setThirdShiftFromTime(calendar.getTime());
			calendar.set(java.util.Calendar.HOUR_OF_DAY, 2);
			cd.setThirdShiftToTime(calendar.getTime());
			// 两个班次
			cd.setShift1(1);
			cd.setShift2(1);
			cd.setShift3(2);
			weekDayCalendarData[i] = cd;
		}
		sCalendar.setWeekDayCalendarData(weekDayCalendarData);
		scheme.getCalendarMap().put(sCalendar.getCalendarUid(), sCalendar);
		log.info("结束初始化系统日历：");
	}

	 
	public Date calFinishDate(SCalendar scalendar, Date startCalDate,
			double estiTime) throws Exception {
		ScheduleScheme scheme = scalendar.getScheme();
		if (scheme == null) {
			log.error("日历调度方案为空" + scalendar);
		}
		int estiSeg = (int) (estiTime / scheme.getScheduleInterval());
		int startSeg = scheme.calSegementFromDate(startCalDate);
		int currSeg = 0;
		int index = startSeg;
		while (currSeg < estiSeg) {
			if (currSeg > scheme.getTotalSegement()) {
				throw new Exception("sdgsdfgdfgdfg");
			}
			// initEndDate上次初始化截止日期
			if (scalendar.getInitEndDate() == null
					|| startCalDate.after(scalendar.getInitEndDate())) {
				// 自动扩展30天
				// 这下面的类型范围还没有弄清楚，86400000*30为一负值，必须加上d
				// 用双精度计算
				long ltime = startCalDate.getTime() + (long) (86400000 * 30d);
				Date initEndDate = new Date(ltime);
				this.initTimeSection(scalendar, initEndDate);
			}
			if (scalendar.getTimeGrid().get(index) != null
					&& (scalendar.getTimeGrid().get(index) == SCalendar.CALENDAR_NOMAL || scalendar
							.getTimeGrid().get(index) == SCalendar.CALENDAR_OVERTIME)) {
				currSeg++;
				// index = index + currSeg;
				//startCalDate = scheme.calDateFromSegement(index);
			}
			index++;
			startCalDate = scheme.calDateFromSegement(index);
		}
		return startCalDate;
	}
}
